/**************************************************************************************
*
*	Copyright (C) 2009 - 2012 Brent Andrew O. Chua - See LICENSE.txt for more info.
*		
*	Filename	-	Model.h
*
*	Description -	All models created are unique. Instancing happens in the lower leve
*					like the geometry, effect, and possibly material.
*
*	Comments	-	
*
*	Modification History:
*			Name			   Date					Description
*			MrCodeSushi	-	06/05/2011	-	Creation of this file
**************************************************************************************/
#ifndef _PSX_MODEL_H_
#define _PSX_MODEL_H_

#include "PulseSTD.h"
#include "ResourcePoolItem.h"
#include "StoragePool.h"
#include "String.h"
#include "GraphicsTypes.h"
#include "PTLBase.h"
#include "Geometry.h"
#include "Effect.h"
#include "Material.h"
#include "ParameterContainer.h"
#include "ParameterBinderMatrixRef.h"

namespace Pulse
{
	struct ModelDesc : public BaseResDesc
	{
		ModelDesc( void );

		~ModelDesc( void );

		void SetToLoad( const CHAR *pFilename );

		void SetManual( Material *pMaterialToSet, Geometry *pGeometryToSet );

		virtual const ResourceCode GetType( void ) const { return ResourceCode( EResource::VIDEO, EWorldResource::MODEL ); }

		void ClearData( void );

		ModelDesc & operator = ( ModelDesc &rhs );

	private:

		friend Model;

		String m_filename;
		Material *m_pMaterialToSet;
		Geometry *m_pGeometryToSet;
	};

	class Model : public IResourcePoolItem
	{
	public:

		virtual ~Model( void );

		// These defines the base interface for all derived resources
		virtual BOOL CreateResource( BaseResDesc *pDesc );
		virtual BOOL DestroyResource( void );
		virtual BOOL LoadResource( void );
		virtual BOOL UnloadResource( void );

		virtual const ResourceCode GetType( void ) const { return ResourceCode( EResource::VIDEO, EWorldResource::MODEL ); }

	public:

		IParameterBinder * AddParameter( IParameter *pParam );

		BOOL RemoveParameter( const CHAR *pParamName );

		void ClearParameters( void );

		Material * GetMaterial( void );

		Geometry * GetGeometry( void );

	private:

		PSX_MakeStoragePoolFriend( Model );

		Model( void );

		EErrorCode::Type Initialize( void );

		void Cleanup( void );		

	private:

		EErrorCode::Type ProcessModel( XMLElementPtr pElem );

		EErrorCode::Type ProcessGeometry( XMLElementPtr pElem );

		EErrorCode::Type ProcessMaterial( XMLElementPtr pElem );

		BOOL VerifyRenderRequirements( void ) const;

	private:

		friend RenderPathForwardPlus;
		friend RenderPathLightPrePass;

		ModelDesc			m_desc;
		Geometry			*m_pGeometry;
		Material			*m_pMaterial;

		ParameterContainer	m_params;
		//ParameterBinderMatrixRef	*m_pBinderTransform;

	};
}

#endif /* _PSX_MODEL_H_ */